package com.aisier.architecture.base

import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
import java.io.ByteArrayOutputStream
import java.io.InputStream

/*
  * ================================================
  * 描述：封装 抽象的 BaseViewModel 基类
  * 作者：zhuangzeqin
  * 时间: 2022/6/10-12:56
  * 邮箱：zzq@eeepay.cn
  * 备注:
  * ----------------------------------------------------------------
  * You never know what you can do until you try !
  *      _              _           _     _   ____  _             _ _
  *     / \   _ __   __| |_ __ ___ (_) __| | / ___|| |_ _   _  __| (_) ___
  *    / _ \ | '_ \ / _` | '__/ _ \| |/ _` | \___ \| __| | | |/ _` | |/ _ \
  *   / ___ \| | | | (_| | | | (_) | | (_| |  ___) | |_| |_| | (_| | | (_) |
  *  /_/   \_\_| |_|\__,_|_|  \___/|_|\__,_| |____/ \__|\__,_|\__,_|_|\___/
  *
  * 签名：最痛苦的事不是我失败了，而是我本可以.--zzq
  * ----------------------------------------------------------------
  * ================================================
  */
abstract class BaseViewModel : ViewModel() {
    private val TAG = "BaseViewModel"

    private val jobs = mutableListOf<Job>()
    var isLoading = MutableLiveData<Boolean>()//标记网络loading状态
    val baseThrowableLiveDate = MutableLiveData<Throwable>()// 错误提示

    private val exceptionHandler = CoroutineExceptionHandler { _, exception ->
        Log.e(TAG, "CoroutineExceptionHandler exception : ${exception.message}")
    }

    protected fun asyncAwait(
        isLoadingFlag: Boolean = true,
        block: suspend CoroutineScope.() -> Unit
    ) =
        viewModelScope.launch {
            supervisorScope {
                try {
                    isLoading.value = isLoadingFlag
                    val deferred = async(exceptionHandler) {
                        block.invoke(this)
                    }
                    deferred.await()
                    isLoading.value = false
                } catch (e: Exception) {
                    isLoading.value = false
                    Log.e(TAG, "asyncAwait:Exception ${e.message} ")
                }
            }
        }.addTo(jobs)

    protected fun asyncLaunch(block: suspend CoroutineScope.() -> Unit) =
        viewModelScope.launch {
            try {
                coroutineScope {
                    block.invoke(this)
                }
            } catch (e: Exception) {
                Log.e(TAG, "asyncLaunch:Exception ${e.message} ")
            }
        }.addTo(jobs)

    //viewmode 的生命周期绑定页面销毁被清除
    override fun onCleared() {
        jobs.forEach { it.cancel() }
        super.onCleared()
    }

    /**
     * 将图片内容解析成字节数组
     */
    @Throws(Exception::class)
    fun readStream(inStream: InputStream): ByteArray? {
        val buffer = ByteArray(1024)
        var len = -1
        val outStream = ByteArrayOutputStream()
        while (inStream.read(buffer).also { len = it } != -1) {
            outStream.write(buffer, 0, len)
        }
        val data = outStream.toByteArray()
        outStream.close()
        inStream.close()
        return data
    }
}

/**
 * 扩展函数，用于viewModel中的job 添加到list方便
 */
private fun Job.addTo(list: MutableList<Job>) {
    list.add(this)
}